{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# 准备数据"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:47:01.995155100Z",
     "start_time": "2023-12-05T05:47:01.989158500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "data": {
      "text/plain": "   customerID  gender  SeniorCitizen Partner Dependents  tenure PhoneService  \\\n0  7590-VHVEG  Female              0     Yes         No       1           No   \n1  5575-GNVDE    Male              0      No         No      34          Yes   \n2  3668-QPYBK    Male              0      No         No       2          Yes   \n3  7795-CFOCW    Male              0      No         No      45           No   \n4  9237-HQITU  Female              0      No         No       2          Yes   \n\n      MultipleLines InternetService OnlineSecurity  ... DeviceProtection  \\\n0  No phone service             DSL             No  ...               No   \n1                No             DSL            Yes  ...              Yes   \n2                No             DSL            Yes  ...               No   \n3  No phone service             DSL            Yes  ...              Yes   \n4                No     Fiber optic             No  ...               No   \n\n  TechSupport StreamingTV StreamingMovies        Contract PaperlessBilling  \\\n0          No          No              No  Month-to-month              Yes   \n1          No          No              No        One year               No   \n2          No          No              No  Month-to-month              Yes   \n3         Yes          No              No        One year               No   \n4          No          No              No  Month-to-month              Yes   \n\n               PaymentMethod MonthlyCharges  TotalCharges Churn  \n0           Electronic check          29.85         29.85    No  \n1               Mailed check          56.95        1889.5    No  \n2               Mailed check          53.85        108.15   Yes  \n3  Bank transfer (automatic)          42.30       1840.75    No  \n4           Electronic check          70.70        151.65   Yes  \n\n[5 rows x 21 columns]",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>customerID</th>\n      <th>gender</th>\n      <th>SeniorCitizen</th>\n      <th>Partner</th>\n      <th>Dependents</th>\n      <th>tenure</th>\n      <th>PhoneService</th>\n      <th>MultipleLines</th>\n      <th>InternetService</th>\n      <th>OnlineSecurity</th>\n      <th>...</th>\n      <th>DeviceProtection</th>\n      <th>TechSupport</th>\n      <th>StreamingTV</th>\n      <th>StreamingMovies</th>\n      <th>Contract</th>\n      <th>PaperlessBilling</th>\n      <th>PaymentMethod</th>\n      <th>MonthlyCharges</th>\n      <th>TotalCharges</th>\n      <th>Churn</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>7590-VHVEG</td>\n      <td>Female</td>\n      <td>0</td>\n      <td>Yes</td>\n      <td>No</td>\n      <td>1</td>\n      <td>No</td>\n      <td>No phone service</td>\n      <td>DSL</td>\n      <td>No</td>\n      <td>...</td>\n      <td>No</td>\n      <td>No</td>\n      <td>No</td>\n      <td>No</td>\n      <td>Month-to-month</td>\n      <td>Yes</td>\n      <td>Electronic check</td>\n      <td>29.85</td>\n      <td>29.85</td>\n      <td>No</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>5575-GNVDE</td>\n      <td>Male</td>\n      <td>0</td>\n      <td>No</td>\n      <td>No</td>\n      <td>34</td>\n      <td>Yes</td>\n      <td>No</td>\n      <td>DSL</td>\n      <td>Yes</td>\n      <td>...</td>\n      <td>Yes</td>\n      <td>No</td>\n      <td>No</td>\n      <td>No</td>\n      <td>One year</td>\n      <td>No</td>\n      <td>Mailed check</td>\n      <td>56.95</td>\n      <td>1889.5</td>\n      <td>No</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>3668-QPYBK</td>\n      <td>Male</td>\n      <td>0</td>\n      <td>No</td>\n      <td>No</td>\n      <td>2</td>\n      <td>Yes</td>\n      <td>No</td>\n      <td>DSL</td>\n      <td>Yes</td>\n      <td>...</td>\n      <td>No</td>\n      <td>No</td>\n      <td>No</td>\n      <td>No</td>\n      <td>Month-to-month</td>\n      <td>Yes</td>\n      <td>Mailed check</td>\n      <td>53.85</td>\n      <td>108.15</td>\n      <td>Yes</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>7795-CFOCW</td>\n      <td>Male</td>\n      <td>0</td>\n      <td>No</td>\n      <td>No</td>\n      <td>45</td>\n      <td>No</td>\n      <td>No phone service</td>\n      <td>DSL</td>\n      <td>Yes</td>\n      <td>...</td>\n      <td>Yes</td>\n      <td>Yes</td>\n      <td>No</td>\n      <td>No</td>\n      <td>One year</td>\n      <td>No</td>\n      <td>Bank transfer (automatic)</td>\n      <td>42.30</td>\n      <td>1840.75</td>\n      <td>No</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>9237-HQITU</td>\n      <td>Female</td>\n      <td>0</td>\n      <td>No</td>\n      <td>No</td>\n      <td>2</td>\n      <td>Yes</td>\n      <td>No</td>\n      <td>Fiber optic</td>\n      <td>No</td>\n      <td>...</td>\n      <td>No</td>\n      <td>No</td>\n      <td>No</td>\n      <td>No</td>\n      <td>Month-to-month</td>\n      <td>Yes</td>\n      <td>Electronic check</td>\n      <td>70.70</td>\n      <td>151.65</td>\n      <td>Yes</td>\n    </tr>\n  </tbody>\n</table>\n<p>5 rows × 21 columns</p>\n</div>"
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv('F:/机器学习数据集/电信客户流失数据/WA_Fn-UseC_-Telco-Customer-Churn.csv')\n",
    "df.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:47:29.901278600Z",
     "start_time": "2023-12-05T05:47:29.729308Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "data": {
      "text/plain": "customerID           object\ngender               object\nSeniorCitizen         int64\nPartner              object\nDependents           object\ntenure                int64\nPhoneService         object\nMultipleLines        object\nInternetService      object\nOnlineSecurity       object\nOnlineBackup         object\nDeviceProtection     object\nTechSupport          object\nStreamingTV          object\nStreamingMovies      object\nContract             object\nPaperlessBilling     object\nPaymentMethod        object\nMonthlyCharges      float64\nTotalCharges         object\nChurn                object\ndtype: object"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dtypes"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:48:15.358024800Z",
     "start_time": "2023-12-05T05:48:15.330066200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "total_charges = pd.to_numeric(df.TotalCharges,errors='coerce') # 将TotalCharges指定为数字形式"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:48:46.090320500Z",
     "start_time": "2023-12-05T05:48:46.071361800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "data": {
      "text/plain": "      customerID TotalCharges\n488   4472-LVYGI             \n753   3115-CZMZD             \n936   5709-LVOEQ             \n1082  4367-NUYAO             \n1340  1371-DWPAZ             \n3331  7644-OMVMY             \n3826  3213-VVOLG             \n4380  2520-SGTTA             \n5218  2923-ARZLG             \n6670  4075-WKNIU             \n6754  2775-SEFEE             ",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>customerID</th>\n      <th>TotalCharges</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>488</th>\n      <td>4472-LVYGI</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>753</th>\n      <td>3115-CZMZD</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>936</th>\n      <td>5709-LVOEQ</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>1082</th>\n      <td>4367-NUYAO</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>1340</th>\n      <td>1371-DWPAZ</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>3331</th>\n      <td>7644-OMVMY</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>3826</th>\n      <td>3213-VVOLG</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>4380</th>\n      <td>2520-SGTTA</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>5218</th>\n      <td>2923-ARZLG</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>6670</th>\n      <td>4075-WKNIU</td>\n      <td></td>\n    </tr>\n    <tr>\n      <th>6754</th>\n      <td>2775-SEFEE</td>\n      <td></td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[total_charges.isnull()][['customerID','TotalCharges']]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:49:22.955426700Z",
     "start_time": "2023-12-05T05:49:22.890424900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [],
   "source": [
    "df.TotalCharges = pd.to_numeric(df.TotalCharges,errors='coerce')\n",
    "df.TotalCharges = df.TotalCharges.fillna(0)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:49:31.250585400Z",
     "start_time": "2023-12-05T05:49:31.197618700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "data": {
      "text/plain": "customerID           object\ngender               object\nSeniorCitizen         int64\nPartner              object\nDependents           object\ntenure                int64\nPhoneService         object\nMultipleLines        object\nInternetService      object\nOnlineSecurity       object\nOnlineBackup         object\nDeviceProtection     object\nTechSupport          object\nStreamingTV          object\nStreamingMovies      object\nContract             object\nPaperlessBilling     object\nPaymentMethod        object\nMonthlyCharges      float64\nTotalCharges        float64\nChurn                object\ndtype: object"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dtypes"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:49:45.242609300Z",
     "start_time": "2023-12-05T05:49:45.233609100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "df.columns = df.columns.str.lower().str.replace(' ','_') # 修改属性名\n",
    "string_columns = list(df.dtypes[df.dtypes=='object'].index)\n",
    "for col in string_columns: # 修改列的内部名称\n",
    "    df[col] = df[col].str.lower().str.replace(' ','_')"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:50:42.896929300Z",
     "start_time": "2023-12-05T05:50:42.810936200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [],
   "source": [
    "df.churn = (df.churn=='yes').astype(int)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:50:44.147768400Z",
     "start_time": "2023-12-05T05:50:44.118754100Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "data": {
      "text/plain": "0    0\n1    0\n2    1\n3    0\n4    1\nName: churn, dtype: int32"
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.churn.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:50:45.065258400Z",
     "start_time": "2023-12-05T05:50:45.043253300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "data": {
      "text/plain": "   customerid  gender  seniorcitizen partner dependents  tenure phoneservice  \\\n0  7590-vhveg  female              0     yes         no       1           no   \n1  5575-gnvde    male              0      no         no      34          yes   \n2  3668-qpybk    male              0      no         no       2          yes   \n3  7795-cfocw    male              0      no         no      45           no   \n4  9237-hqitu  female              0      no         no       2          yes   \n\n      multiplelines internetservice onlinesecurity  ... deviceprotection  \\\n0  no_phone_service             dsl             no  ...               no   \n1                no             dsl            yes  ...              yes   \n2                no             dsl            yes  ...               no   \n3  no_phone_service             dsl            yes  ...              yes   \n4                no     fiber_optic             no  ...               no   \n\n  techsupport streamingtv streamingmovies        contract paperlessbilling  \\\n0          no          no              no  month-to-month              yes   \n1          no          no              no        one_year               no   \n2          no          no              no  month-to-month              yes   \n3         yes          no              no        one_year               no   \n4          no          no              no  month-to-month              yes   \n\n               paymentmethod monthlycharges  totalcharges  churn  \n0           electronic_check          29.85         29.85      0  \n1               mailed_check          56.95       1889.50      0  \n2               mailed_check          53.85        108.15      1  \n3  bank_transfer_(automatic)          42.30       1840.75      0  \n4           electronic_check          70.70        151.65      1  \n\n[5 rows x 21 columns]",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>customerid</th>\n      <th>gender</th>\n      <th>seniorcitizen</th>\n      <th>partner</th>\n      <th>dependents</th>\n      <th>tenure</th>\n      <th>phoneservice</th>\n      <th>multiplelines</th>\n      <th>internetservice</th>\n      <th>onlinesecurity</th>\n      <th>...</th>\n      <th>deviceprotection</th>\n      <th>techsupport</th>\n      <th>streamingtv</th>\n      <th>streamingmovies</th>\n      <th>contract</th>\n      <th>paperlessbilling</th>\n      <th>paymentmethod</th>\n      <th>monthlycharges</th>\n      <th>totalcharges</th>\n      <th>churn</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>7590-vhveg</td>\n      <td>female</td>\n      <td>0</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>1</td>\n      <td>no</td>\n      <td>no_phone_service</td>\n      <td>dsl</td>\n      <td>no</td>\n      <td>...</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no</td>\n      <td>month-to-month</td>\n      <td>yes</td>\n      <td>electronic_check</td>\n      <td>29.85</td>\n      <td>29.85</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>5575-gnvde</td>\n      <td>male</td>\n      <td>0</td>\n      <td>no</td>\n      <td>no</td>\n      <td>34</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>dsl</td>\n      <td>yes</td>\n      <td>...</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no</td>\n      <td>one_year</td>\n      <td>no</td>\n      <td>mailed_check</td>\n      <td>56.95</td>\n      <td>1889.50</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>3668-qpybk</td>\n      <td>male</td>\n      <td>0</td>\n      <td>no</td>\n      <td>no</td>\n      <td>2</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>dsl</td>\n      <td>yes</td>\n      <td>...</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no</td>\n      <td>month-to-month</td>\n      <td>yes</td>\n      <td>mailed_check</td>\n      <td>53.85</td>\n      <td>108.15</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>7795-cfocw</td>\n      <td>male</td>\n      <td>0</td>\n      <td>no</td>\n      <td>no</td>\n      <td>45</td>\n      <td>no</td>\n      <td>no_phone_service</td>\n      <td>dsl</td>\n      <td>yes</td>\n      <td>...</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>no</td>\n      <td>one_year</td>\n      <td>no</td>\n      <td>bank_transfer_(automatic)</td>\n      <td>42.30</td>\n      <td>1840.75</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>9237-hqitu</td>\n      <td>female</td>\n      <td>0</td>\n      <td>no</td>\n      <td>no</td>\n      <td>2</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>fiber_optic</td>\n      <td>no</td>\n      <td>...</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no</td>\n      <td>month-to-month</td>\n      <td>yes</td>\n      <td>electronic_check</td>\n      <td>70.70</td>\n      <td>151.65</td>\n      <td>1</td>\n    </tr>\n  </tbody>\n</table>\n<p>5 rows × 21 columns</p>\n</div>"
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:50:46.166004400Z",
     "start_time": "2023-12-05T05:50:46.119972500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "data": {
      "text/plain": "      customerid  gender  seniorcitizen partner dependents  tenure  \\\n1814  5442-pptjy    male              0     yes        yes      12   \n5946  6261-rcvns  female              0      no         no      42   \n3881  2176-osjuv    male              0     yes         no      71   \n2389  6161-erdgd    male              0     yes        yes      71   \n3676  2364-ufrom    male              0      no         no      30   \n\n     phoneservice multiplelines internetservice       onlinesecurity  ...  \\\n1814          yes            no              no  no_internet_service  ...   \n5946          yes            no             dsl                  yes  ...   \n3881          yes           yes             dsl                  yes  ...   \n2389          yes           yes             dsl                  yes  ...   \n3676          yes            no             dsl                  yes  ...   \n\n         deviceprotection          techsupport          streamingtv  \\\n1814  no_internet_service  no_internet_service  no_internet_service   \n5946                  yes                  yes                   no   \n3881                   no                  yes                   no   \n2389                  yes                  yes                  yes   \n3676                   no                  yes                  yes   \n\n          streamingmovies  contract paperlessbilling  \\\n1814  no_internet_service  two_year               no   \n5946                  yes  one_year               no   \n3881                   no  two_year               no   \n2389                  yes  one_year               no   \n3676                   no  one_year               no   \n\n                  paymentmethod monthlycharges  totalcharges  churn  \n1814               mailed_check          19.70        258.35      0  \n5946    credit_card_(automatic)          73.90       3160.55      1  \n3881  bank_transfer_(automatic)          65.15       4681.75      0  \n2389           electronic_check          85.45       6300.85      0  \n3676           electronic_check          70.40       2044.75      0  \n\n[5 rows x 21 columns]",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>customerid</th>\n      <th>gender</th>\n      <th>seniorcitizen</th>\n      <th>partner</th>\n      <th>dependents</th>\n      <th>tenure</th>\n      <th>phoneservice</th>\n      <th>multiplelines</th>\n      <th>internetservice</th>\n      <th>onlinesecurity</th>\n      <th>...</th>\n      <th>deviceprotection</th>\n      <th>techsupport</th>\n      <th>streamingtv</th>\n      <th>streamingmovies</th>\n      <th>contract</th>\n      <th>paperlessbilling</th>\n      <th>paymentmethod</th>\n      <th>monthlycharges</th>\n      <th>totalcharges</th>\n      <th>churn</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>1814</th>\n      <td>5442-pptjy</td>\n      <td>male</td>\n      <td>0</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>12</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>no</td>\n      <td>no_internet_service</td>\n      <td>...</td>\n      <td>no_internet_service</td>\n      <td>no_internet_service</td>\n      <td>no_internet_service</td>\n      <td>no_internet_service</td>\n      <td>two_year</td>\n      <td>no</td>\n      <td>mailed_check</td>\n      <td>19.70</td>\n      <td>258.35</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>5946</th>\n      <td>6261-rcvns</td>\n      <td>female</td>\n      <td>0</td>\n      <td>no</td>\n      <td>no</td>\n      <td>42</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>dsl</td>\n      <td>yes</td>\n      <td>...</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>yes</td>\n      <td>one_year</td>\n      <td>no</td>\n      <td>credit_card_(automatic)</td>\n      <td>73.90</td>\n      <td>3160.55</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>3881</th>\n      <td>2176-osjuv</td>\n      <td>male</td>\n      <td>0</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>71</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>dsl</td>\n      <td>yes</td>\n      <td>...</td>\n      <td>no</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>no</td>\n      <td>two_year</td>\n      <td>no</td>\n      <td>bank_transfer_(automatic)</td>\n      <td>65.15</td>\n      <td>4681.75</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>2389</th>\n      <td>6161-erdgd</td>\n      <td>male</td>\n      <td>0</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>71</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>dsl</td>\n      <td>yes</td>\n      <td>...</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>one_year</td>\n      <td>no</td>\n      <td>electronic_check</td>\n      <td>85.45</td>\n      <td>6300.85</td>\n      <td>0</td>\n    </tr>\n    <tr>\n      <th>3676</th>\n      <td>2364-ufrom</td>\n      <td>male</td>\n      <td>0</td>\n      <td>no</td>\n      <td>no</td>\n      <td>30</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>dsl</td>\n      <td>yes</td>\n      <td>...</td>\n      <td>no</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>one_year</td>\n      <td>no</td>\n      <td>electronic_check</td>\n      <td>70.40</td>\n      <td>2044.75</td>\n      <td>0</td>\n    </tr>\n  </tbody>\n</table>\n<p>5 rows × 21 columns</p>\n</div>"
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "df_train_full,df_test = train_test_split(df,test_size=0.2,random_state=1)\n",
    "df_train_full.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:50:48.362294700Z",
     "start_time": "2023-12-05T05:50:46.976218600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [],
   "source": [
    "df_train,df_val = train_test_split(df_train_full,test_size=0.33,random_state=11)\n",
    "y_train = df_train.churn.values\n",
    "y_val = df_val.churn.values\n",
    "del df_train['churn']\n",
    "del df_val['churn']"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:50:57.917702800Z",
     "start_time": "2023-12-05T05:50:57.857710800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "data": {
      "text/plain": "customerid          0\ngender              0\nseniorcitizen       0\npartner             0\ndependents          0\ntenure              0\nphoneservice        0\nmultiplelines       0\ninternetservice     0\nonlinesecurity      0\nonlinebackup        0\ndeviceprotection    0\ntechsupport         0\nstreamingtv         0\nstreamingmovies     0\ncontract            0\npaperlessbilling    0\npaymentmethod       0\nmonthlycharges      0\ntotalcharges        0\nchurn               0\ndtype: int64"
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train_full.isnull().sum()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:01.680543Z",
     "start_time": "2023-12-05T05:51:01.640097700Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 探索性数据分析"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "data": {
      "text/plain": "0    4113\n1    1521\nName: churn, dtype: int64"
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train_full.churn.value_counts() # 查看目标变量的分布"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:08.818872400Z",
     "start_time": "2023-12-05T05:51:08.750896700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.270\n"
     ]
    }
   ],
   "source": [
    "global_mean = df_train_full.churn.mean() # 计算流失率\n",
    "print(\"{:.3f}\".format(global_mean))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:14.304998700Z",
     "start_time": "2023-12-05T05:51:14.287009400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [],
   "source": [
    "categorical = ['gender','seniorcitizen','partner','dependents','phoneservice','multiplelines'\n",
    "               ,'internetservice','onlinesecurity','onlinebackup','deviceprotection','techsupport',\n",
    "               'streamingtv','streamingmovies','contract','paperlessbilling','paymentmethod']\n",
    "numerical = ['tenure','monthlycharges','totalcharges']"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:15.410468800Z",
     "start_time": "2023-12-05T05:51:15.386478800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "data": {
      "text/plain": "gender              2\nseniorcitizen       2\npartner             2\ndependents          2\nphoneservice        2\nmultiplelines       3\ninternetservice     3\nonlinesecurity      3\nonlinebackup        3\ndeviceprotection    3\ntechsupport         3\nstreamingtv         3\nstreamingmovies     3\ncontract            3\npaperlessbilling    2\npaymentmethod       4\ndtype: int64"
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train_full[categorical].nunique() # 查看分类变量个数"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:16.305964800Z",
     "start_time": "2023-12-05T05:51:16.076508500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 了解特征的重要性\n",
    "#### 利用流失率来度量特征的重要性"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "female:0.277, male:0.263\n"
     ]
    }
   ],
   "source": [
    "female_mean = df_train_full[df_train_full.gender=='female'].churn.mean()\n",
    "male_mean = df_train_full[df_train_full.gender=='male'].churn.mean()\n",
    "print('female:{:.3f}, male:{:.3f}'.format(female_mean,male_mean))\n",
    "# 分组变量的流失率相差不大,舍去"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:18.075848500Z",
     "start_time": "2023-12-05T05:51:18.048818200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "partner_yes:0.205,partner_no:0.330\n"
     ]
    }
   ],
   "source": [
    "partner_yes = df_train_full[df_train_full.partner=='yes'].churn.mean()\n",
    "partner_no = df_train_full[df_train_full.partner=='no'].churn.mean()\n",
    "print('partner_yes:{:.3f},partner_no:{:.3f}'.format(partner_yes,partner_no))\n",
    "# 分组变量的流失率差异较为明显,保留"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:18.872255500Z",
     "start_time": "2023-12-05T05:51:18.780896500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 风险率\n",
    "<P>在统计学上,不同组之间的比率被称为风险率,其中风险是指产生影响的风险,在上一节中,影响是流失</P>\n",
    "<P>风险=分组率/总体率</P>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "data": {
      "text/plain": "            mean      diff      risk\ngender                              \nfemale  0.276824  0.006856  1.025396\nmale    0.263214 -0.006755  0.974980",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>gender</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>female</th>\n      <td>0.276824</td>\n      <td>0.006856</td>\n      <td>1.025396</td>\n    </tr>\n    <tr>\n      <th>male</th>\n      <td>0.263214</td>\n      <td>-0.006755</td>\n      <td>0.974980</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "global_mean = df_train_full.churn.mean()\n",
    "df_group = df_train_full.groupby(by='gender').churn.agg(['mean']) # 计算AVG(mean)\n",
    "df_group['diff'] = df_group['mean']-global_mean # 计算分组流失率与总体流失率之间的差值\n",
    "df_group['risk'] = df_group['mean']/global_mean # 计算流失的风险\n",
    "df_group"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:21.362348700Z",
     "start_time": "2023-12-05T05:51:20.773292200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [
    {
     "data": {
      "text/plain": "            mean      diff      risk\ngender                              \nfemale  0.276824  0.006856  1.025396\nmale    0.263214 -0.006755  0.974980",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>gender</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>female</th>\n      <td>0.276824</td>\n      <td>0.006856</td>\n      <td>1.025396</td>\n    </tr>\n    <tr>\n      <th>male</th>\n      <td>0.263214</td>\n      <td>-0.006755</td>\n      <td>0.974980</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                   mean      diff      risk\nseniorcitizen                              \n0              0.242270 -0.027698  0.897403\n1              0.413377  0.143409  1.531208",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>seniorcitizen</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>0.242270</td>\n      <td>-0.027698</td>\n      <td>0.897403</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>0.413377</td>\n      <td>0.143409</td>\n      <td>1.531208</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "             mean      diff      risk\npartner                              \nno       0.329809  0.059841  1.221659\nyes      0.205033 -0.064935  0.759472",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>partner</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.329809</td>\n      <td>0.059841</td>\n      <td>1.221659</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.205033</td>\n      <td>-0.064935</td>\n      <td>0.759472</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                mean      diff      risk\ndependents                              \nno          0.313760  0.043792  1.162212\nyes         0.165666 -0.104302  0.613651",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>dependents</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.313760</td>\n      <td>0.043792</td>\n      <td>1.162212</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.165666</td>\n      <td>-0.104302</td>\n      <td>0.613651</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                  mean      diff      risk\nphoneservice                              \nno            0.241316 -0.028652  0.893870\nyes           0.273049  0.003081  1.011412",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>phoneservice</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.241316</td>\n      <td>-0.028652</td>\n      <td>0.893870</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.273049</td>\n      <td>0.003081</td>\n      <td>1.011412</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                      mean      diff      risk\nmultiplelines                                 \nno                0.257407 -0.012561  0.953474\nno_phone_service  0.241316 -0.028652  0.893870\nyes               0.290742  0.020773  1.076948",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>multiplelines</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.257407</td>\n      <td>-0.012561</td>\n      <td>0.953474</td>\n    </tr>\n    <tr>\n      <th>no_phone_service</th>\n      <td>0.241316</td>\n      <td>-0.028652</td>\n      <td>0.893870</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.290742</td>\n      <td>0.020773</td>\n      <td>1.076948</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                     mean      diff      risk\ninternetservice                              \ndsl              0.192347 -0.077621  0.712482\nfiber_optic      0.425171  0.155203  1.574895\nno               0.077805 -0.192163  0.288201",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>internetservice</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>dsl</th>\n      <td>0.192347</td>\n      <td>-0.077621</td>\n      <td>0.712482</td>\n    </tr>\n    <tr>\n      <th>fiber_optic</th>\n      <td>0.425171</td>\n      <td>0.155203</td>\n      <td>1.574895</td>\n    </tr>\n    <tr>\n      <th>no</th>\n      <td>0.077805</td>\n      <td>-0.192163</td>\n      <td>0.288201</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                         mean      diff      risk\nonlinesecurity                                   \nno                   0.420921  0.150953  1.559152\nno_internet_service  0.077805 -0.192163  0.288201\nyes                  0.153226 -0.116742  0.567570",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>onlinesecurity</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.420921</td>\n      <td>0.150953</td>\n      <td>1.559152</td>\n    </tr>\n    <tr>\n      <th>no_internet_service</th>\n      <td>0.077805</td>\n      <td>-0.192163</td>\n      <td>0.288201</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.153226</td>\n      <td>-0.116742</td>\n      <td>0.567570</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                         mean      diff      risk\nonlinebackup                                     \nno                   0.404323  0.134355  1.497672\nno_internet_service  0.077805 -0.192163  0.288201\nyes                  0.217232 -0.052736  0.804660",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>onlinebackup</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.404323</td>\n      <td>0.134355</td>\n      <td>1.497672</td>\n    </tr>\n    <tr>\n      <th>no_internet_service</th>\n      <td>0.077805</td>\n      <td>-0.192163</td>\n      <td>0.288201</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.217232</td>\n      <td>-0.052736</td>\n      <td>0.804660</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                         mean      diff      risk\ndeviceprotection                                 \nno                   0.395875  0.125907  1.466379\nno_internet_service  0.077805 -0.192163  0.288201\nyes                  0.230412 -0.039556  0.853480",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>deviceprotection</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.395875</td>\n      <td>0.125907</td>\n      <td>1.466379</td>\n    </tr>\n    <tr>\n      <th>no_internet_service</th>\n      <td>0.077805</td>\n      <td>-0.192163</td>\n      <td>0.288201</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.230412</td>\n      <td>-0.039556</td>\n      <td>0.853480</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                         mean      diff      risk\ntechsupport                                      \nno                   0.418914  0.148946  1.551717\nno_internet_service  0.077805 -0.192163  0.288201\nyes                  0.159926 -0.110042  0.592390",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>techsupport</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.418914</td>\n      <td>0.148946</td>\n      <td>1.551717</td>\n    </tr>\n    <tr>\n      <th>no_internet_service</th>\n      <td>0.077805</td>\n      <td>-0.192163</td>\n      <td>0.288201</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.159926</td>\n      <td>-0.110042</td>\n      <td>0.592390</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                         mean      diff      risk\nstreamingtv                                      \nno                   0.342832  0.072864  1.269897\nno_internet_service  0.077805 -0.192163  0.288201\nyes                  0.302723  0.032755  1.121328",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>streamingtv</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.342832</td>\n      <td>0.072864</td>\n      <td>1.269897</td>\n    </tr>\n    <tr>\n      <th>no_internet_service</th>\n      <td>0.077805</td>\n      <td>-0.192163</td>\n      <td>0.288201</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.302723</td>\n      <td>0.032755</td>\n      <td>1.121328</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                         mean      diff      risk\nstreamingmovies                                  \nno                   0.338906  0.068938  1.255358\nno_internet_service  0.077805 -0.192163  0.288201\nyes                  0.307273  0.037305  1.138182",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>streamingmovies</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.338906</td>\n      <td>0.068938</td>\n      <td>1.255358</td>\n    </tr>\n    <tr>\n      <th>no_internet_service</th>\n      <td>0.077805</td>\n      <td>-0.192163</td>\n      <td>0.288201</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.307273</td>\n      <td>0.037305</td>\n      <td>1.138182</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                    mean      diff      risk\ncontract                                    \nmonth-to-month  0.431701  0.161733  1.599082\none_year        0.120573 -0.149395  0.446621\ntwo_year        0.028274 -0.241694  0.104730",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>contract</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>month-to-month</th>\n      <td>0.431701</td>\n      <td>0.161733</td>\n      <td>1.599082</td>\n    </tr>\n    <tr>\n      <th>one_year</th>\n      <td>0.120573</td>\n      <td>-0.149395</td>\n      <td>0.446621</td>\n    </tr>\n    <tr>\n      <th>two_year</th>\n      <td>0.028274</td>\n      <td>-0.241694</td>\n      <td>0.104730</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                      mean      diff      risk\npaperlessbilling                              \nno                0.172071 -0.097897  0.637375\nyes               0.338151  0.068183  1.252560",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>paperlessbilling</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>no</th>\n      <td>0.172071</td>\n      <td>-0.097897</td>\n      <td>0.637375</td>\n    </tr>\n    <tr>\n      <th>yes</th>\n      <td>0.338151</td>\n      <td>0.068183</td>\n      <td>1.252560</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "                               mean      diff      risk\npaymentmethod                                          \nbank_transfer_(automatic)  0.168171 -0.101797  0.622928\ncredit_card_(automatic)    0.164339 -0.105630  0.608733\nelectronic_check           0.455890  0.185922  1.688682\nmailed_check               0.193870 -0.076098  0.718121",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>mean</th>\n      <th>diff</th>\n      <th>risk</th>\n    </tr>\n    <tr>\n      <th>paymentmethod</th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>bank_transfer_(automatic)</th>\n      <td>0.168171</td>\n      <td>-0.101797</td>\n      <td>0.622928</td>\n    </tr>\n    <tr>\n      <th>credit_card_(automatic)</th>\n      <td>0.164339</td>\n      <td>-0.105630</td>\n      <td>0.608733</td>\n    </tr>\n    <tr>\n      <th>electronic_check</th>\n      <td>0.455890</td>\n      <td>0.185922</td>\n      <td>1.688682</td>\n    </tr>\n    <tr>\n      <th>mailed_check</th>\n      <td>0.193870</td>\n      <td>-0.076098</td>\n      <td>0.718121</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import display\n",
    "for col in categorical:\n",
    "    df_group = df_train_full.groupby(by=col).churn.agg(['mean'])\n",
    "    df_group['diff'] = df_group['mean'] - global_mean\n",
    "    df_group['risk'] = df_group['mean'] /global_mean\n",
    "    display(df_group)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:23.487460Z",
     "start_time": "2023-12-05T05:51:22.652434500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 互信息\n",
    "<P>两个随机变量的互信息是随机变量之间相互依赖程度的度量</P>"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [
    {
     "data": {
      "text/plain": "                        MI\ncontract          0.098320\nonlinesecurity    0.063085\ntechsupport       0.061032\ninternetservice   0.055868\nonlinebackup      0.046923\ndeviceprotection  0.043453\npaymentmethod     0.043210\nstreamingtv       0.031853\nstreamingmovies   0.031581\npaperlessbilling  0.017589\ndependents        0.012346\npartner           0.009968\nseniorcitizen     0.009410\nmultiplelines     0.000857\nphoneservice      0.000229\ngender            0.000117",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>MI</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>contract</th>\n      <td>0.098320</td>\n    </tr>\n    <tr>\n      <th>onlinesecurity</th>\n      <td>0.063085</td>\n    </tr>\n    <tr>\n      <th>techsupport</th>\n      <td>0.061032</td>\n    </tr>\n    <tr>\n      <th>internetservice</th>\n      <td>0.055868</td>\n    </tr>\n    <tr>\n      <th>onlinebackup</th>\n      <td>0.046923</td>\n    </tr>\n    <tr>\n      <th>deviceprotection</th>\n      <td>0.043453</td>\n    </tr>\n    <tr>\n      <th>paymentmethod</th>\n      <td>0.043210</td>\n    </tr>\n    <tr>\n      <th>streamingtv</th>\n      <td>0.031853</td>\n    </tr>\n    <tr>\n      <th>streamingmovies</th>\n      <td>0.031581</td>\n    </tr>\n    <tr>\n      <th>paperlessbilling</th>\n      <td>0.017589</td>\n    </tr>\n    <tr>\n      <th>dependents</th>\n      <td>0.012346</td>\n    </tr>\n    <tr>\n      <th>partner</th>\n      <td>0.009968</td>\n    </tr>\n    <tr>\n      <th>seniorcitizen</th>\n      <td>0.009410</td>\n    </tr>\n    <tr>\n      <th>multiplelines</th>\n      <td>0.000857</td>\n    </tr>\n    <tr>\n      <th>phoneservice</th>\n      <td>0.000229</td>\n    </tr>\n    <tr>\n      <th>gender</th>\n      <td>0.000117</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import mutual_info_score # 导入计算互信息的函数\n",
    "def calculate_mi(series):\n",
    "    return mutual_info_score(series,df_train_full.churn)\n",
    "\n",
    "df_mi = df_train_full[categorical].apply(calculate_mi) # 对每一列求出它与目标变量的互信息量\n",
    "df_mi = df_mi.sort_values(ascending=False).to_frame(name='MI')# 降序排列\n",
    "df_mi"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:33.111213300Z",
     "start_time": "2023-12-05T05:51:32.952193800Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 相关系数"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [
    {
     "data": {
      "text/plain": "tenure           -0.351885\nmonthlycharges    0.196805\ntotalcharges     -0.196353\ndtype: float64"
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train_full[numerical].corrwith(df_train_full.churn)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:34.963885900Z",
     "start_time": "2023-12-05T05:51:34.903853Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 特征工程,独热编码"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [
    {
     "data": {
      "text/plain": "[{'gender': 'male',\n  'seniorcitizen': 0,\n  'partner': 'yes',\n  'dependents': 'no',\n  'phoneservice': 'yes',\n  'multiplelines': 'no',\n  'internetservice': 'dsl',\n  'onlinesecurity': 'yes',\n  'onlinebackup': 'yes',\n  'deviceprotection': 'yes',\n  'techsupport': 'yes',\n  'streamingtv': 'yes',\n  'streamingmovies': 'yes',\n  'contract': 'two_year',\n  'paperlessbilling': 'yes',\n  'paymentmethod': 'bank_transfer_(automatic)',\n  'tenure': 71,\n  'monthlycharges': 86.1,\n  'totalcharges': 6045.9},\n {'gender': 'female',\n  'seniorcitizen': 1,\n  'partner': 'yes',\n  'dependents': 'no',\n  'phoneservice': 'yes',\n  'multiplelines': 'yes',\n  'internetservice': 'fiber_optic',\n  'onlinesecurity': 'no',\n  'onlinebackup': 'no',\n  'deviceprotection': 'yes',\n  'techsupport': 'no',\n  'streamingtv': 'yes',\n  'streamingmovies': 'yes',\n  'contract': 'one_year',\n  'paperlessbilling': 'yes',\n  'paymentmethod': 'credit_card_(automatic)',\n  'tenure': 60,\n  'monthlycharges': 100.5,\n  'totalcharges': 6029.0},\n {'gender': 'male',\n  'seniorcitizen': 0,\n  'partner': 'no',\n  'dependents': 'no',\n  'phoneservice': 'yes',\n  'multiplelines': 'no',\n  'internetservice': 'dsl',\n  'onlinesecurity': 'no',\n  'onlinebackup': 'no',\n  'deviceprotection': 'no',\n  'techsupport': 'no',\n  'streamingtv': 'no',\n  'streamingmovies': 'no',\n  'contract': 'month-to-month',\n  'paperlessbilling': 'yes',\n  'paymentmethod': 'credit_card_(automatic)',\n  'tenure': 46,\n  'monthlycharges': 45.2,\n  'totalcharges': 2065.15},\n {'gender': 'male',\n  'seniorcitizen': 0,\n  'partner': 'yes',\n  'dependents': 'no',\n  'phoneservice': 'yes',\n  'multiplelines': 'no',\n  'internetservice': 'fiber_optic',\n  'onlinesecurity': 'no',\n  'onlinebackup': 'no',\n  'deviceprotection': 'no',\n  'techsupport': 'no',\n  'streamingtv': 'no',\n  'streamingmovies': 'no',\n  'contract': 'month-to-month',\n  'paperlessbilling': 'yes',\n  'paymentmethod': 'electronic_check',\n  'tenure': 1,\n  'monthlycharges': 69.15,\n  'totalcharges': 69.15},\n {'gender': 'male',\n  'seniorcitizen': 1,\n  'partner': 'no',\n  'dependents': 'no',\n  'phoneservice': 'yes',\n  'multiplelines': 'yes',\n  'internetservice': 'fiber_optic',\n  'onlinesecurity': 'no',\n  'onlinebackup': 'no',\n  'deviceprotection': 'yes',\n  'techsupport': 'no',\n  'streamingtv': 'yes',\n  'streamingmovies': 'yes',\n  'contract': 'month-to-month',\n  'paperlessbilling': 'yes',\n  'paymentmethod': 'electronic_check',\n  'tenure': 20,\n  'monthlycharges': 98.55,\n  'totalcharges': 1842.8}]"
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_dict = df_train[categorical+numerical].to_dict(orient='records') # 将数据框转化为字典列表\n",
    "train_dict[:5]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:42.707428400Z",
     "start_time": "2023-12-05T05:51:42.615430600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "data": {
      "text/plain": "array([[0.00000e+00, 0.00000e+00, 1.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 8.61000e+01, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 1.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 7.10000e+01, 6.04590e+03],\n       [0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00500e+02, 0.00000e+00,\n        0.00000e+00, 1.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 6.00000e+01, 6.02900e+03],\n       [1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 4.52000e+01, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 4.60000e+01, 2.06515e+03],\n       [1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 6.91500e+01, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 6.91500e+01],\n       [1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 9.85500e+01, 0.00000e+00,\n        0.00000e+00, 1.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        0.00000e+00, 0.00000e+00, 1.00000e+00, 1.00000e+00, 0.00000e+00,\n        0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00,\n        1.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+01, 1.84280e+03]])"
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.feature_extraction import DictVectorizer\n",
    "dv = DictVectorizer(sparse=False)\n",
    "dv.fit(train_dict)\n",
    "X_train=dv.transform(train_dict) # 将字典转化为矩阵\n",
    "X_train[:5]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:46.964791Z",
     "start_time": "2023-12-05T05:51:46.465309200Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "outputs": [
    {
     "data": {
      "text/plain": "['contract=month-to-month',\n 'contract=one_year',\n 'contract=two_year',\n 'dependents=no',\n 'dependents=yes',\n 'deviceprotection=no',\n 'deviceprotection=no_internet_service',\n 'deviceprotection=yes',\n 'gender=female',\n 'gender=male',\n 'internetservice=dsl',\n 'internetservice=fiber_optic',\n 'internetservice=no',\n 'monthlycharges',\n 'multiplelines=no',\n 'multiplelines=no_phone_service',\n 'multiplelines=yes',\n 'onlinebackup=no',\n 'onlinebackup=no_internet_service',\n 'onlinebackup=yes',\n 'onlinesecurity=no',\n 'onlinesecurity=no_internet_service',\n 'onlinesecurity=yes',\n 'paperlessbilling=no',\n 'paperlessbilling=yes',\n 'partner=no',\n 'partner=yes',\n 'paymentmethod=bank_transfer_(automatic)',\n 'paymentmethod=credit_card_(automatic)',\n 'paymentmethod=electronic_check',\n 'paymentmethod=mailed_check',\n 'phoneservice=no',\n 'phoneservice=yes',\n 'seniorcitizen',\n 'streamingmovies=no',\n 'streamingmovies=no_internet_service',\n 'streamingmovies=yes',\n 'streamingtv=no',\n 'streamingtv=no_internet_service',\n 'streamingtv=yes',\n 'techsupport=no',\n 'techsupport=no_internet_service',\n 'techsupport=yes',\n 'tenure',\n 'totalcharges']"
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dv.get_feature_names()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T05:51:51.987920900Z",
     "start_time": "2023-12-05T05:51:51.961883200Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 训练逻辑回归"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [
    {
     "data": {
      "text/plain": "LogisticRegression(random_state=1, solver='liblinear')"
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "model = LogisticRegression(random_state=1,solver='liblinear')\n",
    "model.fit(X_train,y_train)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T06:04:42.580170100Z",
     "start_time": "2023-12-05T06:04:40.620291800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "outputs": [
    {
     "data": {
      "text/plain": "array([[0.76509203, 0.23490797],\n       [0.73114243, 0.26885757],\n       [0.68054933, 0.31945067],\n       ...,\n       [0.9427494 , 0.0572506 ],\n       [0.38477113, 0.61522887],\n       [0.93872737, 0.06127263]])"
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "val_dict = df_val[categorical+numerical].to_dict(orient='records') # 与训练时完全相同的方式进行独热编码\n",
    "X_val = dv.transform(val_dict) # 使用之前训练好的变换\n",
    "y_pred = model.predict_proba(X_val)\n",
    "y_pred"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T06:08:46.474194Z",
     "start_time": "2023-12-05T06:08:46.386190200Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 验证集精度"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "验证集精度:80.161%\n"
     ]
    }
   ],
   "source": [
    "print('验证集精度:{:.3f}%'.format(model.score(X_val,y_val)*100))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T06:11:00.175392800Z",
     "start_time": "2023-12-05T06:11:00.152359400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "outputs": [
    {
     "data": {
      "text/plain": "0.8016129032258065"
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_pred = model.predict_proba(X_val)[:,1]\n",
    "churn = y_pred>=0.5\n",
    "(y_val==churn).mean()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T06:15:09.879929900Z",
     "start_time": "2023-12-05T06:15:09.854941500Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 模型解释"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "outputs": [
    {
     "data": {
      "text/plain": "{'contract=month-to-month': 0.563,\n 'contract=one_year': -0.086,\n 'contract=two_year': -0.599,\n 'dependents=no': -0.03,\n 'dependents=yes': -0.092,\n 'deviceprotection=no': 0.1,\n 'deviceprotection=no_internet_service': -0.116,\n 'deviceprotection=yes': -0.106,\n 'gender=female': -0.027,\n 'gender=male': -0.095,\n 'internetservice=dsl': -0.323,\n 'internetservice=fiber_optic': 0.317,\n 'internetservice=no': -0.116,\n 'monthlycharges': 0.001,\n 'multiplelines=no': -0.168,\n 'multiplelines=no_phone_service': 0.127,\n 'multiplelines=yes': -0.081,\n 'onlinebackup=no': 0.136,\n 'onlinebackup=no_internet_service': -0.116,\n 'onlinebackup=yes': -0.142,\n 'onlinesecurity=no': 0.258,\n 'onlinesecurity=no_internet_service': -0.116,\n 'onlinesecurity=yes': -0.264,\n 'paperlessbilling=no': -0.213,\n 'paperlessbilling=yes': 0.091,\n 'partner=no': -0.048,\n 'partner=yes': -0.074,\n 'paymentmethod=bank_transfer_(automatic)': -0.027,\n 'paymentmethod=credit_card_(automatic)': -0.136,\n 'paymentmethod=electronic_check': 0.175,\n 'paymentmethod=mailed_check': -0.134,\n 'phoneservice=no': 0.127,\n 'phoneservice=yes': -0.249,\n 'seniorcitizen': 0.297,\n 'streamingmovies=no': -0.085,\n 'streamingmovies=no_internet_service': -0.116,\n 'streamingmovies=yes': 0.079,\n 'streamingtv=no': -0.099,\n 'streamingtv=no_internet_service': -0.116,\n 'streamingtv=yes': 0.093,\n 'techsupport=no': 0.178,\n 'techsupport=no_internet_service': -0.116,\n 'techsupport=yes': -0.184,\n 'tenure': -0.069,\n 'totalcharges': 0.0}"
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict(zip(dv.get_feature_names(),model.coef_[0].round(3)))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:16:53.058334100Z",
     "start_time": "2023-12-05T07:16:52.246469400Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "outputs": [
    {
     "data": {
      "text/plain": "-0.121988402285897"
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.intercept_[0]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:17:07.840716400Z",
     "start_time": "2023-12-05T07:17:07.800680500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "outputs": [],
   "source": [
    "small_subset = ['contract','tenure','totalcharges']\n",
    "train_dict_small = df_train[small_subset].to_dict(orient='records')\n",
    "dv_small = DictVectorizer(sparse=False)\n",
    "dv_small.fit(train_dict_small)\n",
    "X_small_train = dv_small.transform(train_dict_small)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:21:10.105252400Z",
     "start_time": "2023-12-05T07:21:10.023273300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "outputs": [
    {
     "data": {
      "text/plain": "['contract=month-to-month',\n 'contract=one_year',\n 'contract=two_year',\n 'tenure',\n 'totalcharges']"
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dv_small.get_feature_names()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:21:22.703783700Z",
     "start_time": "2023-12-05T07:21:22.644782900Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "outputs": [
    {
     "data": {
      "text/plain": "LogisticRegression(random_state=1, solver='liblinear')"
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_small = LogisticRegression(random_state=1,solver='liblinear')\n",
    "model_small.fit(X_small_train,y_train)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:23:06.257039Z",
     "start_time": "2023-12-05T07:23:06.191651700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "outputs": [
    {
     "data": {
      "text/plain": "-0.6384442006590022"
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_small.intercept_[0]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:23:29.526213Z",
     "start_time": "2023-12-05T07:23:29.478202700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "outputs": [
    {
     "data": {
      "text/plain": "{'contract=month-to-month': 0.909,\n 'contract=one_year': -0.145,\n 'contract=two_year': -1.403,\n 'tenure': -0.097,\n 'totalcharges': 0.001}"
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict(zip(dv_small.get_feature_names(),model_small.coef_[0].round(3)))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:24:38.811653500Z",
     "start_time": "2023-12-05T07:24:38.762607700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "outputs": [
    {
     "data": {
      "text/plain": "0.7672043010752688"
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "val_small_dict = df_val[small_subset].to_dict(orient='records')\n",
    "X_small_val=dv_small.transform(val_small_dict)\n",
    "model_small.score(X_small_val,y_val)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T07:30:13.096555200Z",
     "start_time": "2023-12-05T07:30:12.996554800Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 删除某些不重要的变量"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "outputs": [
    {
     "data": {
      "text/plain": "array([0.0000e+00, 0.0000e+00, 1.0000e+00, 1.0000e+00, 0.0000e+00,\n       0.0000e+00, 0.0000e+00, 1.0000e+00, 1.0000e+00, 0.0000e+00,\n       0.0000e+00, 8.6100e+01, 1.0000e+00, 0.0000e+00, 0.0000e+00,\n       0.0000e+00, 0.0000e+00, 1.0000e+00, 0.0000e+00, 0.0000e+00,\n       1.0000e+00, 0.0000e+00, 1.0000e+00, 0.0000e+00, 1.0000e+00,\n       1.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00,\n       0.0000e+00, 0.0000e+00, 1.0000e+00, 0.0000e+00, 0.0000e+00,\n       1.0000e+00, 0.0000e+00, 0.0000e+00, 1.0000e+00, 7.1000e+01,\n       6.0459e+03])"
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "categorical_drop = ['seniorcitizen','partner','dependents','multiplelines'\n",
    "               ,'internetservice','onlinesecurity','onlinebackup','deviceprotection','techsupport',\n",
    "               'streamingtv','streamingmovies','contract','paperlessbilling','paymentmethod']\n",
    "numerical = ['tenure','monthlycharges','totalcharges']\n",
    "df_drop_train_dict = df_train[categorical_drop+numerical].to_dict(orient='records')\n",
    "dv_drop = DictVectorizer(sparse=False)\n",
    "dv_drop.fit(df_drop_train_dict)\n",
    "X_train_drop = dv_drop.transform(df_drop_train_dict)\n",
    "X_train_drop[0].T"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T08:12:10.893419800Z",
     "start_time": "2023-12-05T08:12:10.720386Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "outputs": [
    {
     "data": {
      "text/plain": "LogisticRegression(random_state=1, solver='liblinear')"
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_drop = LogisticRegression(random_state=1,solver='liblinear')\n",
    "model_drop.fit(X_train_drop,y_train)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T08:23:32.393914600Z",
     "start_time": "2023-12-05T08:23:32.341882700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "验证集精度:80.269%\n"
     ]
    }
   ],
   "source": [
    "df_drop_val_dict = df_val[categorical_drop+numerical].to_dict(orient='records')\n",
    "X_val = dv_drop.transform(df_drop_val_dict)\n",
    "print('验证集精度:{:.3f}%'.format(model_drop.score(X_val,y_val)*100))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T08:24:01.557088600Z",
     "start_time": "2023-12-05T08:24:01.473090200Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 删除较为重要的属性"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "outputs": [
    {
     "data": {
      "text/plain": "array([1.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 1.0000e+00,\n       0.0000e+00, 1.0000e+00, 1.0000e+00, 0.0000e+00, 0.0000e+00,\n       8.6100e+01, 1.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00,\n       0.0000e+00, 1.0000e+00, 0.0000e+00, 0.0000e+00, 1.0000e+00,\n       0.0000e+00, 1.0000e+00, 0.0000e+00, 1.0000e+00, 1.0000e+00,\n       0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 1.0000e+00,\n       0.0000e+00, 0.0000e+00, 0.0000e+00, 1.0000e+00, 0.0000e+00,\n       0.0000e+00, 1.0000e+00, 0.0000e+00, 0.0000e+00, 1.0000e+00,\n       7.1000e+01, 6.0459e+03])"
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "categorical_drop_important = ['gender','seniorcitizen','partner','dependents','phoneservice','multiplelines'\n",
    "               ,'internetservice','onlinesecurity','onlinebackup','deviceprotection','techsupport',\n",
    "               'streamingtv','streamingmovies','paperlessbilling','paymentmethod']\n",
    "numerical = ['tenure','monthlycharges','totalcharges']\n",
    "df_drop_train_dict_important = df_train[categorical_drop_important+numerical].to_dict(orient='records')\n",
    "dv_drop_important = DictVectorizer(sparse=False)\n",
    "dv_drop_important.fit(df_drop_train_dict_important)\n",
    "X_train_drop_important = dv_drop_important.transform(df_drop_train_dict_important)\n",
    "X_train_drop_important[0].T"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T08:55:13.526957100Z",
     "start_time": "2023-12-05T08:55:13.338972700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "outputs": [
    {
     "data": {
      "text/plain": "LogisticRegression(random_state=1, solver='liblinear')"
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_drop_important = LogisticRegression(random_state=1,solver='liblinear')\n",
    "model_drop_important.fit(X_train_drop_important,y_train)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T08:55:41.382292900Z",
     "start_time": "2023-12-05T08:55:41.340296700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "验证集精度:79.731%\n"
     ]
    }
   ],
   "source": [
    "df_drop_important_val_dict = df_val[categorical_drop_important+numerical].to_dict(orient='records')\n",
    "X_val = dv_drop_important.transform(df_drop_important_val_dict)\n",
    "print('验证集精度:{:.3f}%'.format(model_drop_important.score(X_val,y_val)*100))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2023-12-05T08:56:44.907125700Z",
     "start_time": "2023-12-05T08:56:44.861114Z"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
